$(document).ready(calculator_start);
var g_input_string;

var cal_type_add = 0;
var cal_type_sub = 1;
var cal_type_muti = 2;
var cal_type_div = 3;
var cal_type_none = 4;

//+ - * / 运算符
var NONE_SYM = 0;
var OPER_SYM = 1;
var DOT_SYM = 2;
var NUM_SYM = 3;
var g_cal_finished = 0;

function buildCalculator() {
    var i = 0;
    $("#main-container").append('<div id = "output-container"></div>');
    $("#output-container").append('<textarea id = "dis-area" readonly></textarea>');;
    $("#main-container").append('<div id ="btn-row-1"></div>');
    $("#main-container").append('<div id ="btn-row-2"></div>');
    $("#main-container").append('<div id ="btn-row-3"></div>');

    $("#btn-row-1").append('<button class="btn">C</button>');
    $("#btn-row-1").append('<button class="btn">D</button>');
    $("#btn-row-1").append('<button class="btn">/</button>');
    $("#btn-row-1").append('<button class="btn">*</button>');

    $("#btn-row-1").append('<button class="btn">7</button>');
    $("#btn-row-1").append('<button class="btn">8</button>');
    $("#btn-row-1").append('<button class="btn">9</button>');
    $("#btn-row-1").append('<button class="btn">-</button>');

    $("#btn-row-1").append('<button class="btn">4</button>');
    $("#btn-row-1").append('<button class="btn">5</button>');
    $("#btn-row-1").append('<button class="btn">6</button>');
    $("#btn-row-1").append('<button class="btn">+</button>');

    $("#btn-row-2").append('<button class="btn">1</button>');
    $("#btn-row-2").append('<button class="btn">2</button>');
    $("#btn-row-2").append('<button class="btn">3</button>');

    $("#btn-row-2").append('<button class="btn">()</button>');
    $("#btn-row-2").append('<button class="btn">0</button>');
    $("#btn-row-2").append('<button class="btn">.</button>');

    $("#btn-row-3").append('<button class="btn">=</button>');

}

function clear_key_press_handle(){
    g_input_string = "";
}

function delete_key_press_handle(){
    g_input_string = g_input_string.slice(0, g_input_string.length - 1);
}

function equal_key_press_handle(){
    if ( OPER_SYM == get_last_char_type(g_input_string) || DOT_SYM == get_last_char_type(g_input_string))
        g_input_string = rewrite_last_char(g_input_string,'');

    g_input_string = cal_result(g_input_string);

}

//运算符
function oper_key_press_handle(key){
    if ( g_cal_finished)
        g_cal_finished = 0;
    
    if ( NUM_SYM == get_last_char_type((g_input_string)))
        g_input_string += key;
    else if ( OPER_SYM == get_last_char_type(g_input_string) || DOT_SYM == get_last_char_type(g_input_string))
    {
        g_input_string = rewrite_last_char(g_input_string,key);
    }
}

function dot_key_press_handle(){
    if ( g_cal_finished)
    {    
        g_input_string = "";
        g_cal_finished = 0;
    }

    factor = get_factor(g_input_string);
    if ( 0 == factor.length)
    {
        g_input_string +="0.";
    }
    else if ( !is_sym_in_factor(factor,"."))
        g_input_string += ".";
}

function check_cal_stat()
{
    if ( g_cal_finished)
    {    
        g_input_string = "";
        g_cal_finished = 0;
    }

}

function num_key_press_handle(key){
    if ( g_cal_finished)
    {    
        g_input_string = "";
        g_cal_finished = 0;
    }

    g_input_string += key;
}

function registerOnclickEvent() {
    $(".btn").click(
        function() {
            var curr_btn = $(this).text();
            var factor ="";
            if ("C" == curr_btn) {
                clear_key_press_handle();
            }
            //删除单个字符
            else if ("D" == curr_btn) {
                delete_key_press_handle();
            }
            //等号
            else if ("=" == curr_btn) {
                while ( has_oper_sym(g_input_string) )
                {    
                        equal_key_press_handle();
                        g_cal_finished = 1;
                }
            }
            //运算符"+ - * /"
            else if ( is_oper_symbol(curr_btn)){
                oper_key_press_handle(curr_btn);
            }
            else if ( "." == curr_btn)
            {
                dot_key_press_handle();
            }
            else if ( "()" == curr_btn)
            {

            }
            else {
                num_key_press_handle(curr_btn);
            }

            $("#dis-area").text(g_input_string);
            //console.log($(this).text());
        });
}

//判断是否是运算符号
function is_oper_symbol(c) {
    if ( "+" == c || "-" == c || "*" == c || "/" == c)
        return true;
    else
        return false;
}

//替换最后的字符
function rewrite_last_char(input_string,newLastChar)
{
    var ret = input_string;
    if ( input_string.length == 0)
        return ret;

    var last_idx = input_string.length - 1;
    var sub_string = input_string.slice(0,last_idx);

    if ( newLastChar != '')
        ret = sub_string + newLastChar;
    else
        ret = sub_string;
    return ret;
}

function get_last_char_type(input_string){
    var ret = NONE_SYM;
    var last_idx = input_string.length;
    var last_char = "";
        
    if ( last_idx >= 1)
        last_idx -=1;
    else
        return ret;
    
    last_char = input_string.charAt(last_idx);
    if ( is_oper_symbol(last_char))
        ret = OPER_SYM;
    else if ( is_num(last_char))
        ret = NUM_SYM;
    else if ( "." == last_char)
        ret = DOT_SYM;
    return ret;
}

//最后一个字符是否是运算符
function whether_last_char_is_oper_sym(input_string)
{
    var last_idx = input_string.length - 1;
    if ( is_oper_symbol(input_string.charAt(last_idx)))
        return true;
    else
        return false;

}

//最后一个字符是否是数字
function whether_last_char_is_num(input_string){
    var last_idx = input_string.length - 1;
    if ( is_num(input_string.charAt(last_idx)))
        return true;
    else
        return false;
}

//是否是数字字符
function is_num(c) {
    if (c.charCodeAt(0) >= "48" && c.charCodeAt(0) <= "57")
        return true;
    else
        return false;
}

// 获取运算因数
function get_factor(input_string){

    var ret = input_string;
    var end_idx = input_string.length - 1;
    var begin_idx = end_idx;

    if ( 0 == input_string.length)
        return ret;

    for ( begin_idx = end_idx ; begin_idx >= 0 ; begin_idx--)
    {
        if ( is_oper_symbol( input_string.charAt(begin_idx)))
        {
            if ( begin_idx < end_idx)
                begin_idx += 1;
            break;
        }
        else if ( 0 == begin_idx )
            break;
    }   

    if ( begin_idx == end_idx && ( !is_num(input_string[begin_idx])) )
        ret = "";
    else
        ret = input_string.slice(begin_idx,end_idx +1 );

    console.log("begin_idx:"+begin_idx);
    console.log("factor:"+ret);
    return ret;
}

function has_oper_sym(input_string){
    var ret = false;
    if ( input_string.indexOf("+") != -1)
        ret = true;
    else if ( input_string.indexOf("-") != -1)
        ret = true;
    else if ( input_string.indexOf("*") != -1)
        ret = true;
    else if ( input_string.indexOf("/") != -1)
        ret = true;
    return ret;
}

function is_sym_in_factor(factor,sym){
    if ( factor.indexOf(sym) != -1)
        return true;
    else
        return false;
}

function get_min_plus_num(num1, num2) {
    var ret_num = 0;
    if (num1 == num2 || (num1 < 0 && num2 < 0)) {
        ret = num1;
    } else if (num1 < 0 && num2 > 0) {
        ret_num = num2;
    } else if (num >= 0 && num2 < 0) {
        ret_num = num1;
    } else if (num1 < num2) {
        ret_num = num1;
    } else
        ret_num = num2;

    return ret_num;
}

function get_next_cal_param(input_string) {

    var multi_oper_idx = 0;
    var div_oper_idx = 0;
    var add_oper_idx = 0;
    var sub_oper_idx = 0;

    var first_handle_oper_idx = 0;
    var cal_type = cal_type_add;

    add_oper_idx = input_string.indexOf("+");
    sub_oper_idx = input_string.indexOf("-");
    multi_oper_idx = input_string.indexOf("*");
    div_oper_idx = input_string.indexOf("/");

    if (add_oper_idx < 0 && sub_oper_idx < 0 && multi_oper_idx < 0 && div_oper_idx < 0) {
        cal_type = cal_type_none;
        first_handle_oper_idx = -1;
    } else {
        // 存在乘除运算
        if (multi_oper_idx > 0 || div_oper_idx > 0) {
            if (multi_oper_idx > 0 && div_oper_idx > 0) {
                if (multi_oper_idx < div_oper_idx) {
                    first_handle_oper_idx = multi_oper_idx;
                    cal_type = cal_type_muti;
                } else {
                    first_handle_oper_idx = div_oper_idx;
                    cal_type = cal_type_div;
                }
            } else if (multi_oper_idx < 0) {
                first_handle_oper_idx = div_oper_idx;
                cal_type = cal_type_div;

            } else {
                first_handle_oper_idx = multi_oper_idx;
                cal_type = cal_type_muti;

            }
        } else {
            if (add_oper_idx > 0 && sub_oper_idx > 0) {
                if (add_oper_idx < sub_oper_idx) {
                    first_handle_oper_idx = add_oper_idx;
                    cal_type = cal_type_add;
                } else {
                    first_handle_oper_idx = sub_oper_idx;
                    cal_type = cal_type_sub;
                }
            } else if (add_oper_idx < 0) {
                first_handle_oper_idx = sub_oper_idx;
                cal_type = cal_type_sub;

            } else {
                first_handle_oper_idx = add_oper_idx;
                cal_type = cal_type_add;
            }
        }
    }

    return [cal_type, first_handle_oper_idx];
}

function cal_result(input_string) {
    var multi_oper_idx = 0;
    var div_oper_idx = 0;
    var first_handle_oper_idx = 0;
    var left_var = 0;
    var right_var = 0;
    var pos = 0;
    var left_begin_pos = 0;
    var right_end_pos = 0;
    var cal_type = cal_type_add;
    var cal_res = "";
    var ret = "";

    var cal_params = get_next_cal_param(input_string);

    first_handle_oper_idx = cal_params[1];
    cal_type = cal_params[0];
    if (cal_type == cal_type_none) {
        ret = input_string;
    } else {
        // cut left val
        for (pos = first_handle_oper_idx - 1; pos > 0; pos--) {
            if (!is_num(input_string[pos]) &&  input_string[pos] != ".") {
                pos += 1;
                break;
            }
        }

        left_begin_pos = pos;
        left_var = input_string.slice(pos, first_handle_oper_idx);

        // cut right val
        for (pos = first_handle_oper_idx + 1; pos < input_string.length; pos++) {
            if (!is_num(input_string[pos]) &&  input_string[pos] != ".") {
                pos -= 1;
                break;
            }

        }
        if (pos >= input_string.length)
            pos -= 1;
        right_end_pos = pos;

        right_var = input_string.slice(first_handle_oper_idx + 1, right_end_pos + 1);

        cal_res = cal(left_var, right_var, cal_type);

        ret = input_string.slice(0, left_begin_pos);
        ret = ret + cal_res + input_string.slice(right_end_pos + 1, input_string.length);
    }
    console.log("ret1:" + ret);
    console.log("ret2:" + cal_res);
    console.log("ret3:" + input_string.slice(right_end_pos + 1, input_string.length));

    /*
    console.log("oper_pos:"+first_handle_oper_idx);
    console.log("left_pos:"+left_begin_pos);
    console.log("right_pos:"+right_end_pos);
    console.log("pos:"+pos);
    console.log("left:"+left_var);
    console.log("right:"+right_var);
    console.log("cal_result:"+cal_res);
    */
    return ret;
}

//返回值为0?
function cal(left_val, right_val, cal_type) {
    var ret = 0;
    left_val = Number(left_val);
    right_val = Number(right_val);
    if (cal_type == cal_type_add) {
        //ret = left_val + right_val;
        ret = floatAdd(left_val,right_val);
    } else if (cal_type == cal_type_sub) {
        //ret = left_val - right_val;
        ret = floatAdd(left_val,-right_val);
    } else if (cal_type == cal_type_muti) {
        ret = floatMul(left_val,right_val);
//        ret = left_val * right_val;
    } else if (cal_type == cal_type_div) {
        //ret = left_val / right_val;
        ret = floatDiv(left_val,right_val);
    }
    return ret;
}

function keyboard_key_down_handle() {
    console.log("code_down:" + event.code);
    if ('Backspace' == event.code) {
        delete_key_press_handle();
    }
    else if ('Delete' == event.code)
        clear_key_press_handle();
    $("#dis-area").text(g_input_string);
}


function keyboard_key_press_handle(){
    console.log("code_press:"+event.keyCode);
    var keyCode = event.keyCode;
    var keyVal ="";
    // num key 0 -> 9
    if ( keyCode >= 48 && keyCode <= 57){
        keyVal = keyCode - 48;
        num_key_press_handle(keyVal);
        //console.log("keyVal:"+keyVal);
    }
    // key : + - * /
    else if ( 43 == keyCode || 45 == keyCode || 42 == keyCode || 47 == keyCode)
    {
        if ( 43 == keyCode)
            keyVal = "+";
        else if ( 45 == keyCode)
            keyVal = "-";
        else if ( 42 == keyCode)
            keyVal = "*";
        else
            keyVal = "/";

        oper_key_press_handle(keyVal);
    }
    // key : == ,enter
    else if ( 61 == keyCode || 13 == keyCode){
        keyVal = "=";
        while ( has_oper_sym(g_input_string) )
        {
            equal_key_press_handle();
            g_cal_finished = 1;
        }
    }
    else if ( 46 == keyCode){
        keyVal =".";
        dot_key_press_handle();
    }
    else if ( 8 == keyCode){
        keyVal = "D";
        delete_key_press_handle();
    }
    $("#dis-area").text(g_input_string);

}

function floatAdd(arg1,arg2){
    var r1,r2,m;
    try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
    try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
    m=Math.pow(10,Math.max(r1,r2));
    return (arg1*m+arg2*m)/m;
}

function floatMul(arg1,arg2){
    var s1 = arg1.toString(),s2 = arg2.toString(),m = 0;
    try{m+=s1.toString().split(".")[1].length}catch(e){}
    try{m+=s2.toString().split(".")[1].length}catch(e){}

    return Number(s1.replace(".","") * Number(s2.replace(".",""))/Math.pow(10,m));
}

function floatDiv(arg1,arg2){
    var t1 = 0,t2 = 0,r1,r2;
    try{t1 = arg1.toString().split(".")[1].length}catch(e){}
    try{t2 = arg2.toString().split(".")[1].length}catch(e){}

    with(Math){
        console.log(9*pow(10,-3));
        r1 = Number(arg1.toString().replace(".",""));
        r2 = Number(arg2.toString().replace(".",""));
        return floatMul((r1/r2),pow(10,t2-t1));
    }
}

function init() {
    g_input_string = "";
    buildCalculator();
    registerOnclickEvent();
    document.addEventListener("keypress",keyboard_key_press_handle);
    document.addEventListener("keydown",keyboard_key_down_handle);
}

function calculator_start() {
    init();
}
